﻿using Microsoft.Extensions.DependencyInjection;
using Leo.Core.Abp.Client.Contracts;
using Refit;
using System;
using System.Collections.Generic;
using System.Net.Http;

namespace Leo.Core.Abp.Client
{
    public static class BaseHttpApiClientExtentions
    {
        public static void AddAbpHttpClientRefitServiceProxy(this IServiceCollection services, BaseHttpApiClientOptions httpApiClientOptions)
        {
          
            var configuration = services.GetConfiguration();

            var hostUrl = configuration[httpApiClientOptions.RemoteSectionName];
            try
            {
                // add jwt token support
                var httpClientBuilder = services.AddHttpClient(httpApiClientOptions.RemoteServiceName, x =>
                {
                    x.BaseAddress = new Uri(hostUrl);
                }).ConfigurePrimaryHttpMessageHandler(x=> services.GetRequiredService<TokenRequestMessageHandler>());

                if (httpApiClientOptions.DelegatingHandlerFunc != null)
                {
                    httpClientBuilder.ConfigurePrimaryHttpMessageHandler(httpApiClientOptions.DelegatingHandlerFunc);
                }

                if (httpApiClientOptions.HttpErrorPolicy != null)
                {
                    httpClientBuilder.AddTransientHttpErrorPolicy(httpApiClientOptions.HttpErrorPolicy);
                }

                if (httpApiClientOptions.PolicySelector != null)
                {
                    httpClientBuilder.AddPolicyHandler(httpApiClientOptions.PolicySelector);
                }

                var allRefitServiceProxyTypes = new List<Type>();

                foreach (var item in httpApiClientOptions.ContractsAssemblies)
                {
                    allRefitServiceProxyTypes.AddRange(item.GetTypes());
                }
                allRefitServiceProxyTypes = allRefitServiceProxyTypes.FindAll(t => t.IsInterface && typeof(IRefitServiceProxy).IsAssignableFrom(t));

                foreach (var type in allRefitServiceProxyTypes)
                {
                    services.AddRefitClient(type, httpApiClientOptions.RemoteServiceName);
                }
            }
            catch
            {

            }
        }

        public static IServiceCollection AddRefitClient(this IServiceCollection services, Type refitInterfaceType, string httpclientName, RefitSettings settings = null)
        {
            var builder = RequestBuilder.ForType(refitInterfaceType, settings);
            services.AddSingleton(provider => builder);
            services.AddSingleton(refitInterfaceType, provider =>
            {
                var client = provider.GetService<IHttpClientFactory>()?.CreateClient(httpclientName);

                if (client == null)
                    throw new ArgumentException($"please inject the httpclient named {httpclientName} httpclient!! ", httpclientName);

                client.DefaultRequestHeaders.Add("abp-api-client", "refit");
                return RestService.For(refitInterfaceType, client, builder);
            });
            return services;
        }

        public static IServiceCollection AddRefitClient(this IServiceCollection services, Type refitInterfaceType, HttpClient client, RefitSettings settings = null)
        {
            var builder = RequestBuilder.ForType(refitInterfaceType, settings);
            services.AddSingleton(provider => builder);
            services.AddSingleton(refitInterfaceType, provider =>
            {
                return RestService.For(refitInterfaceType, client, builder);
            });
            return services;
        }
    }
}
